/**
 *  @desc 下拉框
 */
import React from 'react';
import { Select } from 'antd';
import Input from '../input';
import { getTempData } from '../_common/wrapXhr';
import _,{ debounce } from 'lodash';
interface receiveProps {
  api?: Object; //接口参数，包含（url:接口地址，params:发送的数据，一旦发送数据默认GET）
  data?: Array<any>; //显示的数据，格式 ：['选项一', '选项二'] 或 [{ name: '选项一', code: 1 }, { name: '选项二', code: 2 }];
  map?: {
    value: 'code' | string | number;
    text: 'name' | string;
  }; // 属性映射,未了匹配不同的业务
  extCode?: Array<string>; // 排除选中值
  placeholder?: string;
  editable?: Boolean;
  wrapResultData?: (a: any) => {};
  componentType?: 'Select' | 'Input';
  initDefaultValue?: boolean; // 是否使用 option 第一个值作为默认值
  _value?: string;
  useStateDiff?: boolean; // 是否用state中的oldApi来比较
  include?: string[]; // 用来对数据做过滤
  [key: string]: any;
}

export default class BiZSelect extends React.Component<receiveProps, any> {
  constructor(props: receiveProps) {
    super(props);
    let value: any = this.props.value;
    if (this.props.mode) {
      value = this.props.value ? this.props.value : [];
    }
    this.state = {
      data: [],
      value,
      caseLikeValue: undefined,
      oldApi: {},
    };
  }

  componentWillReceiveProps(nextProps: any) {
    if (nextProps.api
      && (JSON.stringify(nextProps.api) != JSON.stringify(this.props.api)
        || (nextProps.useStateDiff
          && JSON.stringify(nextProps.api) != JSON.stringify(this.state.oldApi)))) {
      this.setState({
        oldApi: _.cloneDeep(nextProps.api),
      });
      this.getData(nextProps.api);
    }
    if (nextProps.value && JSON.stringify(nextProps.value) != JSON.stringify(this.state.value)) {
      if (this.props.sign == 1) {
        const value = (this.props && this.props?.map?.value) || 'code';
        this.setState({ value: nextProps.value[value] });
      } else {
        this.setState({ value: nextProps.value });
      }
    }
    /**
     * 表单重置为空时，重置只能Select组件state
     * @BUG #XRMDM-280 2019年10月10日15:41:03 周旺生
     */
    const nextValue = nextProps.value;
    if (!nextValue && nextValue !== this.state.value) {
      this.setState({ value: nextValue });
    }
  }

  componentDidMount() {
    if (this.props.api) {
      this.setState({
        oldApi: _.cloneDeep(this.props.api),
      });
      this.getData(this.props.api);
    }
  }

  getData = async (api: any) => {
    this.setState({
      data: [],
    });
    try {
      if (api?.url) {
        const data: any = await getTempData(api);
        const { extCode, wrapResultData } = this.props;
        // fix:设置一个包裹函数用来处理返回值不符合要求自定义
        let tempData = wrapResultData ? wrapResultData(data) : data;
        if (extCode && Array.isArray(extCode) && extCode.length) {
          tempData = data?.filter((item: any) => {
            return extCode.indexOf(item.code) < 0;
          });
        }
        this.setState({ data: tempData }, () => {
          // 获取数据之后对下拉值进行赋值
          this.triggerDefaultInit();
        });
      }
    } catch (err) {
      console.warn(`select组件-getData发生错误:${err}`);
    }
  };

  onChange(value: any) {
    const { onChange } = this.props;
    let { data = [], api } = this.props;
    if (api) data = this.state.data;
    if (onChange) {
      const v = (this.props && this.props?.map?.value) || 'code';
      const item = data.find((i) => i[v] == value);
      if (this.props.sign == 1) {
        onChange(item, data, item);
      } else if (this.props.sign == 2) {
        onChange(value, item, data);
      } else {
        onChange(value, data, item);
      }
    }
    this.setState({ value });
  }

  triggerDefaultInit = () => {
    const { data } = this.state;
    const { initDefaultValue, objCode = 'code', onChangeValue, value, onChange } = this.props;
    if (initDefaultValue && data?.length > 0 && data[0][objCode]) {
      this.onChange(data[0][objCode]);
    }
    if(onChangeValue && data?.length > 0 && value){
      const item = data.filter((i:any)=>(value?.includes(i.code)));
      if(this.props?.sign == 4){
        onChange(value, item, item[0]);
      }else {
        onChange(value, item, data);
      }
    }
  };

  handleSearch = (likeValue: string) => {
    const caseLikeValue = likeValue?.toLocaleUpperCase() || '';
    this.setState({
      caseLikeValue,
    });
  };

  transformData = (data: any[]) => {
    if (!data || data.length <= 0 || !this?.props?.include?.length) {
      return data || [];
    }
    const v = (this.props && this.props?.map?.value) || 'code';
    return data.filter(item => {
      return this.props.include.includes(item[v]);
    });
  }

  render() {
    let { map, data = [],_value, api, objCode = 'code', mode, componentType, editable } = this.props;
    let { value, data: stateData, caseLikeValue } = this.state;
    console.log('this.state', this.state)
    const { value: mapCode, text: mapName } = map || {
      value: 'code',
      text: 'name',
    };

    const code = mapCode || 'code';
    const name = mapName || 'name';

    if (objCode && value && typeof value === 'object' && value[objCode]) {
      value = value[objCode];
    }
    if (mode === 'multiple' && !value) {
      value = [];
    }
    if (api) {
      data = stateData;
    }
    return editable ? (
      componentType === 'Input' ? (
        <Input {...this.props} />
      ) : (
        <Select
          optionFilterProp="label"
          showSearch
          filterOption={false}
          onSearch={debounce(this.handleSearch, 500)}
          {...this.props}
          onChange={this.onChange.bind(this)}
          value={value}
          options={this.transformData(data)
            .map((i: any) => {
              return {
                value: typeof i == 'object' ? i[code] : i,
                label: typeof i == 'object' ? i[name] : i,
              };
            })
            .filter((item) => {
              const { value: optionValue, label } = item;
              return !caseLikeValue
                ? true
                : optionValue?.toLocaleUpperCase().includes(caseLikeValue) ||
                label?.toLocaleUpperCase().includes(caseLikeValue);
            })}
        />
      )
    ) : (
      <span> {_value || value}</span>
    );
  }
}
